package threadcoreknowledge.threadobjectclasscommonmethods;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * @ClassName ProducerConsumerModel
 * @Description TODO 用wait/notify实现生产者、消费者
 * @Author wushaopei
 * @Date 2021/4/20 6:26
 * @Version 1.0
 */
public class ProducerConsumerModel {

    public static void main(String[] args) {
        EventStorage eventStorage = new EventStorage();
        Producer producer = new Producer(eventStorage);
        Consumer consumer = new Consumer(eventStorage);
        new Thread(producer).start();
        new Thread(consumer).start();
    }
}
// 生产者
class Producer implements Runnable{
    private EventStorage storage;

    public Producer(EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100; i ++){
            storage.put();
        }
    }
}
// 消费者
class Consumer implements Runnable{
    private EventStorage storage;

    public Consumer(EventStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        for(int i = 0; i < 100; i ++){
            storage.take();
        }
    }
}

class EventStorage{
    private int maxSize;
    private LinkedList<Date> storage;

    public EventStorage(){
        maxSize=10;
        storage = new LinkedList<>();
    }
    // 生产数据
    public synchronized void put(){
        // 当list的size等于maxSize，说明队列满了，生产者阻塞住
        while (storage.size() == maxSize){
            try {
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        // 生产者被消费者唤醒，继续生产
        storage.add(new Date());
        System.out.println("仓库里有了" + storage.size() + "个产品");
        // 生产者生产之后唤醒消费者继续消费
        notify();
    }

    // 消费数据
    public synchronized void take(){
        // 仓库没有数据，消费者进入阻塞
        while (storage.size() == 0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        // 消费者被唤醒，继续消费数据
        System.out.println("拿到了" + storage.poll() + "，现在仓库还剩下" + storage.size());
        // 唤醒生产者继续生产，每消费完一个数据，队列都会空出一个位置，此时可以唤醒生产者
        notify();
    }
}